// The NSpring Framework for .NET
// Copyright (c) 2003, Jeffrey Varszegi
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, 
// are permitted provided that the following conditions are met:
// 
// - Redistributions of source code must retain the above copyright notice, this 
// list of conditions and the following disclaimer.
// 
// - Redistributions in binary form must reproduce the above copyright notice, this 
// list of conditions and the following disclaimer in the documentation and/or other 
// materials provided with the distribution.
// 
// - Neither the name of the NSpring project nor the names of its contributors may 
// be used to endorse or promote products derived from this software without 
// specific prior written permission from the copyright owner.
// 
// - No product derived from this software may be called "NSpring", nor may 
// "NSpring" appear in the name of such a product, without specific prior written 
// permission from the copyright owner.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
// OF THE POSSIBILITY OF SUCH DAMAGE. 

namespace NSpring.Logging.Exceptions {

using System;
using System.Collections;

/// <summary>
/// Encapsulates information about an exception that incurred during logging.
/// Allows rerouting of events through another logger, or any other object that
/// implements the ExceptionHandler interface
/// </summary>
public sealed class LoggerException : ApplicationException {
    private const string Exception_DESCRIPTION                  = "Logging exception";
    private const string BATCH_Exception_DESCRIPTION            = "Batch logging exception";
    
    private ArrayList exceptionsList                            = new ArrayList();

    /// <summary>
    /// If IsComposite is true, this property contains a collection of 
    /// logging exceptions which occurred during a bulk-writing operation
    /// </summary>
    public LoggerException[] Exceptions {
        get {
            lock (exceptionsList) {
                LoggerException[] returnValue = new LoggerException[exceptionsList.Count];
                exceptionsList.CopyTo(returnValue);
                return returnValue;
            }
        }
    }

    /// <summary>
    /// Indicates whether this exception is actually a batch of logging exceptions
    /// which occurred during a bulk writing operation
    /// </summary>
    public readonly bool IsBatchException;
    
    /// <summary>
    /// The Logger instance that threw the exception indicating its inability to
    /// log an event
    /// </summary>
    public readonly Logger Logger;
    
    /// <summary>
    /// The NSpring.Logging.Event that wasn't able to be logged by the Logger
    /// instance throwing the exception
    /// </summary>
    public readonly NSpring.Logging.Event Event;
    
    /// <summary>
    /// The exception (inner exception) thrown by the Logger that wasn't able
    /// to successfully log the event; this will be null if IsComposite is true
    /// </summary>
    public readonly Exception Exception;
    
    /// <summary>
    /// Constructs a new LoggerException instance, indicating a failure to log
    /// an application event
    /// </summary>
    /// <param name="_logger">The Logger instance that failed to log the event</param>
    /// <param name="_event">The application event that couldn't be successfully logged</param>
    /// <param name="_exception">The exception thrown by the logger (becomes this instance's inner exception)</param>
    public LoggerException(Logger _logger, NSpring.Logging.Event _event, Exception _exception) : base(Exception_DESCRIPTION, _exception) {
        if ((_logger == null) || (_event == null) || (_exception == null)) {
            throw new ArgumentNullException();
        }
        Logger = _logger;
        Event = _event;
        Exception = _exception;
        IsBatchException = false;
    }
    
    public LoggerException(LoggerException[] exceptions) : base(BATCH_Exception_DESCRIPTION) {
        Exception = null;
        IsBatchException = true;
        if (exceptions != null) {
            LoggerException le;
            for(int x = 0; x < exceptions.Length; x++) {
                le = exceptions[x];
                if (le != null) {
                    exceptionsList.Add(le);
                }
            }
        }
    }

    public LoggerException() : base(BATCH_Exception_DESCRIPTION) {
        Exception = null;
        IsBatchException = true;
    }

    public static LoggerException CreateBatchException(Logger _logger, Event[] _events, Exception _exception) {
        if ((_logger == null) || (_events == null) || (_exception == null)) {
            throw new ArgumentNullException();
        }
        LoggerException le = new LoggerException();
        Event e;
        for(int x = 0; x < _events.Length; x++) {
            e = _events[x];
            if (e != null) {
                le.AddException(_logger, e, _exception);
            }
        }
        return le;
    }
    
    public void AddException(Logger _logger, NSpring.Logging.Event _event, Exception _exception) {
        if ((_logger == null) || (_event == null) || (_exception == null)) {
            throw new ArgumentNullException();
        }
        lock (exceptionsList) {
            exceptionsList.Add(new LoggerException(_logger, _event, _exception));
        }
    }
}

}
